// src/main/java/com/dbms/execution/execution/Predicate.java
package com.dbms.execution.execution;

import com.dbms.common.Tuple;

/**
 * Predicate (谓词) 用于评估一个或两个元组是否满足某个条件。
 * 它被 FilterExecutor (用于 WHERE 子句) 和 JoinExecutor (用于 ON 子句) 使用。
 * 【已修改】这个版本增加了对多种比较操作符（如 ">", "<", "!="）的支持。
 */
public class Predicate {

    private final int leftFieldIndex;  // 左操作数的字段索引
    private final int rightFieldIndex; // 右操作数的字段索引 (仅用于 Join)
    private final Object constantValue;   // 常量值 (仅用于 Filter)
    private final String operator;      // 【新增】存储操作符，如 "=", ">", "<"
    private final boolean isJoin;       // 标志位，区分是用于 Filter 还是 Join

    /**
     * 构造函数 - 用于 Filter (例如 WHERE id > 10)
     * @param fieldIndex 要比较的元组中的字段索引 (例如 `id` 的索引)
     * @param op         比较操作符 (例如 `>`)
     * @param value      要比较的常量值 (例如 `10`)
     */
    public Predicate(int fieldIndex, String op, Object value) {
        this.leftFieldIndex = fieldIndex;
        this.operator = op;
        this.constantValue = value;
        this.isJoin = false;
        this.rightFieldIndex = -1; // Filter 模式下不使用
    }

    /**
     * 构造函数 - 用于 Join (例如 ON table1.colA = table2.colB)
     * @param leftFieldIndex  左边元组的连接字段索引 (例如 `table1.colA` 的索引)
     * @param rightFieldIndex 右边元组的连接字段索引 (例如 `table2.colB` 的索引)
     */
    public Predicate(int leftFieldIndex, int rightFieldIndex) {
        this.leftFieldIndex = leftFieldIndex;
        this.rightFieldIndex = rightFieldIndex;
        this.operator = "="; // Join 默认是等值连接
        this.isJoin = true;
        this.constantValue = null; // Join 模式下不使用
    }

    /**
     * 评估单个元组 (用于 FilterExecutor)。
     * @param tuple 待评估的元组
     * @return 如果元组满足条件则返回 true，否则返回 false
     */
    public boolean evaluate(Tuple tuple) {
        if (isJoin) {
            throw new IllegalStateException("This predicate is configured for joins, not filters.");
        }
        Object tupleValue = tuple.getValue(leftFieldIndex);

        // 【核心修改】使用 switch 语句来处理不同的比较操作符。
        // 为了能进行大小比较，我们将操作数强制转换为 Comparable 接口。
        // 这要求被比较的字段类型（如 Integer, String）都实现了该接口。
        @SuppressWarnings({"unchecked", "rawtypes"})
        Comparable left = (Comparable) tupleValue;
        @SuppressWarnings({"unchecked", "rawtypes"})
        Comparable right = (Comparable) constantValue;

        switch (this.operator) {
            case "=":
                return left.equals(right);
            case ">":
                return left.compareTo(right) > 0;
            case "<":
                return left.compareTo(right) < 0;
            case ">=":
                return left.compareTo(right) >= 0;
            case "<=":
                return left.compareTo(right) <= 0;
            case "!=":
            case "<>": // SQL 中两种不等号的表示
                return !left.equals(right);
            default:
                throw new UnsupportedOperationException("Unsupported operator in predicate: " + this.operator);
        }
    }

    /**
     * 评估两个元组 (用于 JoinExecutor)。
     * @param leftTuple 左表元组
     * @param rightTuple 右表元组
     * @return 如果两个元组满足连接条件则返回 true，否则返回 false
     */
    public boolean evaluate(Tuple leftTuple, Tuple rightTuple) {
        if (!isJoin) {
            throw new IllegalStateException("This predicate is configured for filters, not joins.");
        }
        Object leftValue = leftTuple.getValue(leftFieldIndex);
        Object rightValue = rightTuple.getValue(rightFieldIndex);
        // 当前只支持等值连接。这里也可以扩展为支持非等值连接。
        return leftValue.equals(rightValue);
    }

    /**
     * 获取左字段索引（用于 HashJoin）。
     */
    public int getLeftFieldIndex() {
        return leftFieldIndex;
    }

    /**
     * 获取右字段索引（用于 HashJoin）。
     */
    public int getRightFieldIndex() {
        return rightFieldIndex;
    }

    /**
     * 【新增】重写 toString 方法，用于在 EXPLAIN 的输出中提供更可读的谓词信息。
     */
    @Override
    public String toString() {
        if (isJoin) {
            return "JOIN ON (left_idx=" + leftFieldIndex + " = right_idx=" + rightFieldIndex + ")";
        } else {
            return "(col_idx=" + leftFieldIndex + " " + operator + " " + constantValue + ")";
        }
    }
}